/**
 * This class is handeling all request towards the wow-armory.
 * THIS IS HOW AN EXAMPLE URI LOOKS LIKE:
 * ALL:        http://eu.wowarmory.com/search.xml?searchQuery=Klakaballe&searchType=all
 * SPECIFIC:   http://eu.wowarmory.com/character-sheet.xml?r=Twisting+Nether&cn=Klakaballe
 * EXPLAINED: SEARCH FOR ALL PLAYERS:
 * 
 * http://<REGION>.wowarmory.com/search.xml?searchQuery=<CHARACTERNAME>&searchType=<TYPEOFSEARCH>
 * 
 * <REGION>         = EU, US, .. [only EU supported as of June 2010..
 * <CHARACTERNAME>  = The specified character..
 * <TYPEOFSEARCH> = Type of search.. [
 * 
 * 
 * EXPLAINED: SEARCH FOR SPECIFIC CHARACTER:
 * 
 * http://<REGION>.wowarmory.com/character-sheet.xml?r=<REALMNAME>&n=<CHARACTERNAME>
 * 
 * 
 * <REALMNAME>     = Realmname. E.g Twisting+Nether or Vashj
 * <CHARACTERNAME> = Charactername. E.g Klakaballe / Ratual / Crealock
 * 
 * @author vegard.aasen
 * @since 21.06.2010
 * 
 */

package wowarmory;

import general.Initializer;
import general.WarlockAppIntegrator;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumMap;
import java.util.List;

import javax.swing.SwingWorker;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import character.Alliance;
import character.ClassOperationType;
import character.ClassType;
import character.Faction;
import character.Gender;
import character.Profession;
import character.ResistanceTypes;
import character.WowCharacter;
import character.WowCharacterProfession;
import character.WowCharacterPvP;
import character.WowCharacterStatistics;
import character.WowCharacterTalents;
import charactergear.ArmorRarity;
import charactergear.CharacterGearType;
import charactergear.CharacterItem;

public class ImportCharacter extends SwingWorker<Object, Void> {
	
	private WarlockAppIntegrator appIntegrator = new WarlockAppIntegrator();
	
	private static final String USER_AGENT_PROPERTY = "User-Agent";
	private static final String USER_AGENT_VALUE = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1";
	private static final String ENCODING = "utf-8";
	
	protected String charName;
	protected Object realmName;
	protected String regionType;
	
	/**
	 * WOW ELEMENTS THAT WE'RE LOADING..
	 */
	protected WowCharacter wowcharacter = new WowCharacter();
	protected List<WowCharacterProfession> currProfession = new ArrayList<WowCharacterProfession>();
	protected WowCharacterPvP wowcharacterpvp = new WowCharacterPvP();
	protected WowCharacterStatistics wowstats = new WowCharacterStatistics();
	protected WowCharacterTalents wowtalents = new WowCharacterTalents();
	protected List<CharacterItem> wowcharitems = new ArrayList<CharacterItem>();
	
	private Initializer initializer;
	
	protected ArrayList<Integer> characterItemIds;
		
	//GENERAL NOTE:	
	//The object type for this method needs to be changed when the program changes.
	//I need to put it into the <main> program - that is; The "Do-Some-Stuff-File..??"
	@Override
	protected Object doInBackground() throws Exception {
		
		return null;
	}
	
	public ImportCharacter (String charName, String realmName, String regionType) {
		setCharName(charName);
		setRealmName(realmName);
		setRegionType(regionType);
		
		characterItemIds = new ArrayList<Integer>();
	}
	
	public void testMethod() throws Exception {

	}
	
	/**
	 * 
	 * @return true/false
	 * @throws Exception
	 */
	
	@SuppressWarnings({ "unchecked" })
	public WarlockAppIntegrator fetchCharacterDataFromWowArmory() throws Exception {
		boolean characterLoaded = false;
	
		URL armoryUrl = generateUrlForUser(regionType, charName, realmName.toString());

		Document document = retrieveDocumentForConnection(armoryUrl);
		
		//TODO: Create error handling for characters that are NOT found..
				
		Element rootElementOfResponse = document.getRootElement();
		Element characterInformation = rootElementOfResponse.getChild("characterInfo");
		Element characterClass = characterInformation.getChild("character");

		/**
		 * These are the objects where we store the current data for the 
		 * current given character
		 */
			
		@SuppressWarnings("unused")
		int validRaceIds[] = {1, 3, 4, 7, 11, 2, 5, 6, 8, 10};
		
		//setting the different values for the character 
		//NOTE: [CHAR ONLY!! - TALENTS, GUILD, PROFESSIONS, ITEMS, GLYPHS, ENCHANTS WILL COME LATER!!] 
		
		wowcharacter.setCharName(characterClass.getAttributeValue("name"));
		wowcharacter.setCharLevel(Integer.valueOf(characterClass.getAttributeValue("level")));
		System.out.println("Found character: " + wowcharacter.getCharName() +
				" @ Level " + wowcharacter.getCharLevel() + 
				". Fetching more data.");
		
		
		Integer genderId = Integer.valueOf(characterClass.getAttributeValue("genderId"));
		Gender gender = genderId==0 ? Gender.MALE : Gender.FEMALE;		
		wowcharacter.setCharGender(gender);
		
		int raceId = Integer.valueOf(characterClass.getAttributeValue("raceId"));
		Enum<?> raceType = wowcharacter.getCurrentRaceType(raceId);
		WowRealms characterRealm = new WowRealms();
		Enum faction = null; 
		
		wowcharacter.setRaceId(raceId);
		if(raceType.getClass().equals(Alliance.class)){
			//ALLIANCE :-)
			faction = Faction.ALLIANCE;
			wowcharacter.setCharRace(raceType);
			if(wowcharacter.getCharGender()!=null){
				EnumMap<Gender, Enum<?>> map = new EnumMap<Gender, Enum<?>>(Gender.class);
				map.put((Gender) wowcharacter.getCharGender(), raceType);
				wowcharacter.setGenderAndCharacterRace(map);
			}
			wowcharacter.setCharFaction(faction);
		} else {
			//ITS HORDE :-)
			faction = Faction.HORDE;
			wowcharacter.setCharRace(raceType);
			if(wowcharacter.getCharGender()!=null){ 
				EnumMap<Gender, Enum<?>> map = new EnumMap<Gender, Enum<?>>(Gender.class);
				map.put((Gender) wowcharacter.getCharGender(), raceType);
				wowcharacter.setGenderAndCharacterRace(map);
			}
			wowcharacter.setCharFaction(faction);
		}
		
		if(!characterClass.getAttributeValue("prefix").equals("")){
			wowcharacter.setCharTitle(characterClass.getAttributeValue("prefix"));
		} else if(!characterClass.getAttributeValue("suffix").equals("")) {
			wowcharacter.setCharTitle(characterClass.getAttributeValue("suffix"));
		}
		wowcharacter.setAchievementPoints(Integer.valueOf(characterClass.getAttributeValue("points")));
		wowcharacter.setBattleGroup(characterClass.getAttributeValue("battleGroup"));
		wowcharacter.setGuildName(characterClass.getAttributeValue("guildName"));
		wowcharacter.setGuildUri(characterClass.getAttributeValue("guildUrl"));
		
		characterRealm.setRealmName(characterClass.getAttributeValue("realm"));
		
		wowcharacter.setRealm(characterRealm); // this is also generated from the search..
		
		wowcharacter.setLastModified(characterClass.getAttributeValue("lastModified"));
		
		int classId = Integer.valueOf(characterClass.getAttributeValue("classId"));
		Enum<?> classType = wowcharacter.getCurrentClassType(classId);
		wowcharacter.setClassType((Enum<ClassType>) classType); // this is not unchecked - will always be the damn CLASSTYPE SHIZZLE!!
		wowcharacter.setCharacterUrl(armoryUrl); // Just using the one already defined earlier..No need for getting this one!! :-) [ I think..]
		
		System.out.println("Character data loaded..\r\nStarting to load Character info..");
		Element characterOpenTab = characterInformation.getChild("characterTab");
		
		//shooting through the professions
		Element profession = characterOpenTab.getChild("professions");
		for(Element skill : (Collection<Element>) profession.getChildren()) {
			String p = "";
			WowCharacterProfession loopedWCP = new WowCharacterProfession();
			for(Profession prof : Profession.values()){
				if(!currProfession.contains(prof)) {
					if(prof.toString().equals(skill.getAttributeValue("name"))){
						p = prof.returnNameOfProfession();
						loopedWCP.setProfessionName(p);
						loopedWCP.setCurProfessionCap(skill.getAttributeValue("max"));
						loopedWCP.setCurProfessionValue(skill.getAttributeValue("value"));
						loopedWCP.setProfessionKeyReference(skill.getAttributeValue("key"));
						currProfession.add(loopedWCP);
					}
				}
			}
			currProfession.add(loopedWCP);
		}
		
		System.out.println("Professions has been set up..\r\nStarting to load pvp history..");
		
		Element pvp = characterOpenTab.getChild("pvp");
		for(Element pvppart : (Collection<Element>) pvp.getChildren()) {
			if(pvppart.getValue().equals("lifetimehonorablekills")){
				wowcharacterpvp.setHonorKills(Double.parseDouble(pvppart.getAttributeValue("value")));
			}else{ 
				wowcharacterpvp.setArenaCurrency(Double.parseDouble(pvppart.getAttributeValue("value")));
			}
		}
		
		print("Pvp statistics has been set up..\r\nStarting to load characterstats..");
		
		print("\t   i) Loading resistances..");
		
		Element resistances = characterOpenTab.getChild("resistances");
		EnumMap<ResistanceTypes, Integer> resTypesMap = 
			new EnumMap<ResistanceTypes, Integer>(ResistanceTypes.class);
		for(Element resistance : (Collection<Element>) resistances.getChildren()) {
			String resistanceName = resistance.getName().toString();
			Integer resistanceValue = Integer.parseInt(resistance.getAttributeValue("value"));
			if(ResistanceTypes.comareStringToResistanceType
					(resistanceName)) {
				ResistanceTypes currResType = null;
				currResType = ResistanceTypes.findCoherentResType(resistanceName);
				resTypesMap.put(currResType, resistanceValue);
			}
		}
		
		if(resTypesMap!=null) {
			wowstats.setResistanceMap(resTypesMap);
		}
		
		print("\t  ii) Loading Base statistics..");
		
		Element baseStatistics = characterOpenTab.getChild("baseStats");
		for(Element baseStat : (Collection<Element>) baseStatistics.getChildren()){
			if(baseStat.getName().equals("strength")) {
				wowstats.setStrAttack(Integer.parseInt(baseStat.getAttributeValue("attack")));
				wowstats.setStrBase(Integer.parseInt(baseStat.getAttributeValue("base")));
				wowstats.setStrEffective(Integer.parseInt(baseStat.getAttributeValue("effective")));
			}else if(baseStat.getName().equals("agility")) {
				wowstats.setAgiArmor(Integer.parseInt(baseStat.getAttributeValue("armor")));
				wowstats.setAgiAttack(Integer.parseInt(baseStat.getAttributeValue("attack")));
				wowstats.setAgiBase(Integer.parseInt(baseStat.getAttributeValue("base")));
				wowstats.setAgiCritHitPercent(Double.parseDouble(baseStat.getAttributeValue("critHitPercent")));
				wowstats.setAgiEffective(Integer.parseInt(baseStat.getAttributeValue("effective")));
			}else if(baseStat.getName().equals("stamina")){
				wowstats.setStaBase(Integer.parseInt(baseStat.getAttributeValue("base")));
				wowstats.setStaEffective(Integer.parseInt(baseStat.getAttributeValue("effective")));
				wowstats.setStaHealth(Integer.parseInt(baseStat.getAttributeValue("health")));
				wowstats.setStaPetBonus(Integer.parseInt(baseStat.getAttributeValue("petBonus")));
			}else if(baseStat.getName().equals("intellect")){
				wowstats.setIntBase(Integer.parseInt(baseStat.getAttributeValue("base")));
				wowstats.setIntCritHitPercent(Double.parseDouble(baseStat.getAttributeValue("critHitPercent")));
				wowstats.setIntEffective(Integer.parseInt(baseStat.getAttributeValue("effective")));
				wowstats.setIntMana(Integer.parseInt(baseStat.getAttributeValue("mana")));
				wowstats.setIntPetBonus(Integer.parseInt(baseStat.getAttributeValue("petBonus")));
			}else if(baseStat.getName().equals("spirit")){
				wowstats.setSpiBase(Integer.parseInt(baseStat.getAttributeValue("base")));
				wowstats.setSpiEffective(Integer.parseInt(baseStat.getAttributeValue("effective")));
				wowstats.setSpiHealthRegen(Integer.parseInt(baseStat.getAttributeValue("healthRegen")));
				wowstats.setSpiManaRegen(Integer.parseInt(baseStat.getAttributeValue("manaRegen")));
			}else if(baseStat.getName().equals("armor")){
				wowstats.setArmorBase(Integer.parseInt(baseStat.getAttributeValue("base")));
				wowstats.setArmorEffective(Integer.parseInt(baseStat.getAttributeValue("effective")));
				wowstats.setArmorPercentReduce(Double.parseDouble(baseStat.getAttributeValue("percent")));
				wowstats.setArmorPetBonus(Integer.parseInt(baseStat.getAttributeValue("petBonus")));
			}
		}
		
		//TODO: As of today (22.06.2010):
		//If the person is a e.g ROGUE, I dont give a rats ass about stats for SPELL
		//THO I'm including some of the other stuff either way from the TANK-part and RANGED-part..
		
		print("\t iii) Loading (depending on class and type def.) MELEE, RANGED, TANK statistics..");
		
		Element talents = characterOpenTab.getChild("talentSpecs");
		for(Element currentTalent : (Collection<Element>) talents.getChildren()) {
			//TODO: NOTE!! HERE IM JUST LOOPING OVER THE CURRENT ( !!! ) TALENT SPECC
			//I DONT GIVE A SHIT ABOUT SECOND TALENT TREEs
			//COMING IN FUTURE VERSION
			if(currentTalent.getAttributeValue("active")!=null) {
				wowtalents.setFirstTree(Integer.parseInt(currentTalent.getAttributeValue("treeOne")));
				wowtalents.setSecondTree(Integer.parseInt(currentTalent.getAttributeValue("treeTwo")));
				wowtalents.setThirdTree(Integer.parseInt(currentTalent.getAttributeValue("treeThree")));
			}
		}
		ClassOperationType classOptType = (ClassOperationType)wowcharacter.getCurrentCharacterType((ClassType)wowcharacter.getClassType(), wowtalents);
		print("\t  iv) Loading stuff for type: " + classOptType);
		
		if(classOptType.equals(ClassOperationType.MELEE)){
			if(loadAllMeleeRelatedStats(document)){
				print("\t\t o) " + classOptType + " specifics loaded..");
			}
		} else if (classOptType.equals(ClassOperationType.TANK)) {
			if(loadAllTankRelatedStats(document)){
				print("\t\t o) " + classOptType + " specifics loaded..");
			}
		} else if (classOptType.equals(ClassOperationType.RANGED) || 
				classOptType.equals(ClassOperationType.HEALER)) {			
			if(loadAllRangedRelatedStats(document)){
				print("\t\t o) " + classOptType + " specifics loaded..");
			}
		} else {
			//ClassOperationType.UNDEFINED..Loading everything..
			loadAllMeleeRelatedStats(document);
			loadAllRangedRelatedStats(document);
			loadAllTankRelatedStats(document);
			print("\t\t o) Loaded everything as your class are " + classOptType);
		}
		//THIS HAPPENS EITHER WAY:
		loadAllExtraStats(document);
		print("\t\t o) Loaded the normal extra stuff as well..");
		
		print("\t   v) Loading itemsdata. Building structure..");
		
		Element items = characterOpenTab.getChild("items");
		
		CharacterItem currCharItem;
		for(Element item : (Collection<Element>) items.getChildren()) {
			currCharItem = new CharacterItem();
			currCharItem.setEnchantId((item.getAttributeValue("permanentEnchantItemId")!=null ? Integer.parseInt(item.getAttributeValue("permanentEnchantItemId")) : new Integer(0)));
			currCharItem.setItemDurability(Integer.parseInt(item.getAttributeValue("maxDurability")));
			currCharItem.setItemGearType(CharacterGearType.ARMOR);
			currCharItem.setItemIconId(item.getAttributeValue("icon"));
			currCharItem.setItemId(Integer.parseInt(item.getAttributeValue("id")));
			currCharItem.setItemLevel(Integer.parseInt(item.getAttributeValue("level")));
			currCharItem.setItemName(item.getAttributeValue("name"));
			currCharItem.setItemRarity(ArmorRarity.getCurrentItemRarity(Integer.parseInt(item.getAttributeValue("rarity"))));
			
			wowcharitems.add(currCharItem); //adding item
		}
		
		/*
		for(CharacterItem c : wowcharitems) {
			print ("RARITY: " + c.getItemRarity() + " LEVEL " + c.getItemLevel());
		}
		*/
		
		
		if(wowcharacter!=null){
			characterLoaded = true;
		}
		
		//TODO: Remember to do the following:
		//Apply the professions to the instance of the application
		//Apply the charactersettings to the instance of the application
		//Apply the pvphistory to the instance of the application
		//Apply the statistics to the instance of the application
		
		
		//SETTING UP THE INTEGRATOR!!
		appIntegrator.setWowcharacter(wowcharacter);
		appIntegrator.setWowcharacterpvp(wowcharacterpvp);
		appIntegrator.setWowcharitems(wowcharitems);
		appIntegrator.setWowstats(wowstats);
		appIntegrator.setWowtalents(wowtalents);
		
		return characterLoaded ? appIntegrator : null;
	}
	
	/**
	 * 
	 * @return true/false
	 * @throws Exception
	 */
	public boolean fetchCharacterTalentTreeFromWowArmory() throws Exception {
		boolean characterDoesReallyExists = false;
		
		URL armoryUrl = generateUrlForUser(regionType, charName, realmName.toString());

		Document document = retrieveDocumentForConnection(armoryUrl);
		
		Element rootElementOfResponse = document.getRootElement();
		//fetching talentree for current character..
		Element talentElement = rootElementOfResponse.getChild("characterInfo").getChild("talents");
		
		return characterDoesReallyExists;
	}
	
	public boolean fetchCharacterItemsFromWowArmory() {
		//not in use yet..
		return true;
	}
	
	/*
	 * 
	 * HELPER METHODS
	 *  
	 */
	
	protected Document retrieveDocumentForConnection(URL uriForArmory) 
	throws IOException, 
	JDOMException {
		Document responseDocument;
		if(uriForArmory!=null) {
			HttpURLConnection connectionTowardsArmory = (HttpURLConnection) uriForArmory.openConnection();
			
			connectionTowardsArmory.addRequestProperty(USER_AGENT_PROPERTY, USER_AGENT_VALUE);
			connectionTowardsArmory.setRequestProperty("Cookie", "loginChecked=1");
			
			//TODO: REMOVE THESE
			System.out.println("Armory URL: " + uriForArmory);
			System.out.println("Armory Response: " + connectionTowardsArmory.getResponseMessage());
			
			SAXBuilder builder = new SAXBuilder();
			
			BufferedReader reader = new BufferedReader(new InputStreamReader(connectionTowardsArmory.getInputStream()));
			
			responseDocument = builder.build(reader);
		} else {
			responseDocument = new Document();
		}
		
		return responseDocument;
	}
	
	protected URL generateUrlForUser(String regionName, String userName, String realmName) 
	throws MalformedURLException, 
	UnsupportedEncodingException {
		String armoryURI = "http://";
		armoryURI += regionName; // adding region
		armoryURI += ".wowarmory.com/character-sheet.xml?r=";
		armoryURI += URLEncoder.encode(realmName, ENCODING); // adding realmname - needs to be encoded with utf-8!!!
		armoryURI += "&n=";
		armoryURI += URLEncoder.encode(userName, ENCODING); // adding charname - needs to be encoded with utf-8!!!
		
		URL actuallyArmoryURI = new URL(armoryURI);

		return actuallyArmoryURI;
	}
	
	@SuppressWarnings("unchecked")
	protected boolean loadAllMeleeRelatedStats(Document source) {
		Element rootElementOfResponse = source.getRootElement();
		Element characterInformation = rootElementOfResponse.getChild("characterInfo");
		Element charaterTab = characterInformation.getChild("characterTab");
		Element melee = charaterTab.getChild("melee");
		
		for(Element meleeInfo : (Collection<Element>) melee.getChildren()){
			if(meleeInfo.getName().equals("mainHandDamage")){
				wowstats.setMhDps(Double.parseDouble(meleeInfo.getAttributeValue("dps")));
				wowstats.setMhMax(Double.parseDouble(meleeInfo.getAttributeValue("max")));
				wowstats.setMhMin(Double.parseDouble(meleeInfo.getAttributeValue("min")));
				wowstats.setMhPercent(Double.parseDouble(meleeInfo.getAttributeValue("percent")));
				wowstats.setMhSpeed(Double.parseDouble(meleeInfo.getAttributeValue("speed")));
			}
			if(meleeInfo.getName().equals("offHandDamage")){
				wowstats.setOhDps(Double.parseDouble(meleeInfo.getAttributeValue("dps")));
				wowstats.setOhMax(Double.parseDouble(meleeInfo.getAttributeValue("max")));
				wowstats.setOhMin(Double.parseDouble(meleeInfo.getAttributeValue("min")));
				wowstats.setOhPercent(Double.parseDouble(meleeInfo.getAttributeValue("percent")));
				wowstats.setOhSpeed(Double.parseDouble(meleeInfo.getAttributeValue("speed")));
			}
			if(meleeInfo.getName().equals("mainHandSpeed")){
				wowstats.setMhHastePercent(Double.parseDouble(meleeInfo.getAttributeValue("hastePercent")));
				wowstats.setMhHasteRating(Double.parseDouble(meleeInfo.getAttributeValue("hasteRating")));
				wowstats.setMhSpeedOfMainHand(Double.parseDouble(meleeInfo.getAttributeValue("value")));
			}
			if(meleeInfo.getName().equals("offHandSpeed")){
				wowstats.setOhHastePercent(Double.parseDouble(meleeInfo.getAttributeValue("hastePercent")));
				wowstats.setOhHasteRating(Double.parseDouble(meleeInfo.getAttributeValue("hasteRating")));
				wowstats.setoHSpeedOfOffHand(Double.parseDouble(meleeInfo.getAttributeValue("value")));
			}
			if(meleeInfo.getName().equals("power")) {
				wowstats.setPwrBase(Double.parseDouble(meleeInfo.getAttributeValue("base")));
				wowstats.setPwrEffective(Double.parseDouble(meleeInfo.getAttributeValue("effective")));
				wowstats.setPwrIncDps(Double.parseDouble(meleeInfo.getAttributeValue("increasedDps")));
			}
			if(meleeInfo.getName().equals("hitRating")){
				wowstats.setMeleeIncHitPercent(Double.parseDouble(meleeInfo.getAttributeValue("increasedHitPercent")));
				wowstats.setMeleePenetration(Double.parseDouble(meleeInfo.getAttributeValue("penetration")));
				wowstats.setMeleeReducedArmorPercent(Double.parseDouble(meleeInfo.getAttributeValue("reducedArmorPercent")));
				wowstats.setMeleeHitRating(Double.parseDouble(meleeInfo.getAttributeValue("value")));
			}
			if(meleeInfo.getName().equals("critChance")){
				wowstats.setMeleeCritPercent(Double.parseDouble(meleeInfo.getAttributeValue("percent")));
				wowstats.setMeleeCritExtraPercent(Double.parseDouble(meleeInfo.getAttributeValue("plusPercent")));
				wowstats.setMeleeCritRating(Double.parseDouble(meleeInfo.getAttributeValue("rating")));
			}
			if(meleeInfo.getName().equals("expertise")){
				wowstats.setMeleeExpAdditional(Double.parseDouble(meleeInfo.getAttributeValue("additional")));
				wowstats.setMeleeExpValue(Double.parseDouble(meleeInfo.getAttributeValue("value")));
				wowstats.setMeleeExpRating(Double.parseDouble(meleeInfo.getAttributeValue("rating")));
				wowstats.setMeleeExpPercent(Double.parseDouble(meleeInfo.getAttributeValue("percent")));
			}
			wowstats.setMeleeHasBeenSetUp(true);
		}
		return wowstats.isMeleeHasBeenSetUp();
	}
	
	@SuppressWarnings("unchecked")
	protected boolean loadAllRangedRelatedStats(Document source) {
		Element rootElementOfResponse = source.getRootElement();
		Element characterInformation = rootElementOfResponse.getChild("characterInfo");
		Element charaterTab = characterInformation.getChild("characterTab");
		Element res = charaterTab.getChild("spell");		
		for(Element resInfo : (Collection<Element>) res.getChildren()){
			if(resInfo.getName().equals("bonusDamage")) {
				for(Element bonus : (Collection<Element>) resInfo.getChildren()) {
					if(bonus.getName().equals("arcane")){
						wowstats.setSpBonusDmgArcane(Double.parseDouble(bonus.getAttributeValue("value")));
					}
					if(bonus.getName().equals("fire")){
						wowstats.setSpBonusDmgFire(Double.parseDouble(bonus.getAttributeValue("value")));
					}
					if(bonus.getName().equals("frost")){
						wowstats.setSpBonusDmgFrost(Double.parseDouble(bonus.getAttributeValue("value")));
					}
					if(bonus.getName().equals("holy")){
						wowstats.setSpBonusDmgHoly(Double.parseDouble(bonus.getAttributeValue("value")));
					}
					if(bonus.getName().equals("nature")){
						wowstats.setSpBonusDmgNature(Double.parseDouble(bonus.getAttributeValue("value")));
					}
					if(bonus.getName().equals("shadow")){
						wowstats.setSpBonusDmgShadow(Double.parseDouble(bonus.getAttributeValue("value")));
					}
					//this value can return -1..
					if(bonus.getName().equals("petBonus")){
						wowstats.setSpBonusDmgPetBonus(Double.parseDouble(bonus.getAttributeValue("damage")));
					}
				}
			}
			if(resInfo.getName().equals("bonusHealing")){
				wowstats.setSpBonusHealing(Double.parseDouble(resInfo.getAttributeValue("value")));
			}
			if(resInfo.getName().equals("hitRating")){
				wowstats.setSpHitIncHitPercent(Double.parseDouble(resInfo.getAttributeValue("increasedHitPercent")));
				wowstats.setSpHitPenetration(Double.parseDouble(resInfo.getAttributeValue("penetration")));
				wowstats.setSpHitRating(Double.parseDouble(resInfo.getAttributeValue("value")));
				wowstats.setSpHitReducedResist(Double.parseDouble(resInfo.getAttributeValue("reducedResist")));
			}
			if(resInfo.getName().equals("critChance")){
				wowstats.setSpCritRating(Double.parseDouble(resInfo.getAttributeValue("rating")));
			}
			if(resInfo.getName().equals("penetration")){
				wowstats.setSpPenetrationRating(Double.parseDouble(resInfo.getAttributeValue("value")));
			}
			if(resInfo.getName().equals("manaRegen")){
				wowstats.setSpManaRegenCastingRating(Double.parseDouble(resInfo.getAttributeValue("casting")));
				wowstats.setSpManaRegenNotCastingRating(Double.parseDouble(resInfo.getAttributeValue("notCasting")));
			}
			if(resInfo.getName().equals("hasteRating")){
				wowstats.setSpHastePercent(Double.parseDouble(resInfo.getAttributeValue("hastePercent")));
				wowstats.setSpHasteRating(Double.parseDouble(resInfo.getAttributeValue("hasteRating")));
			}
		}
		return (wowstats.getSpHastePercent()!=null&&wowstats.getSpBonusHealing()!=null) ? true : false;
	}
	
	@SuppressWarnings("unchecked")
	protected boolean loadAllTankRelatedStats(Document source) {
		Element rootElementOfResponse = source.getRootElement();
		Element characterInformation = rootElementOfResponse.getChild("characterInfo");
		Element charaterTab = characterInformation.getChild("characterTab");
		Element res = charaterTab.getChild("defenses");		
		for(Element resInfo : (Collection<Element>) res.getChildren()){
			if(resInfo.getName().equals("defense")) {
				wowstats.setDefenseDecPercent(Double.parseDouble(resInfo.getAttributeValue("decreasePercent")));
				wowstats.setDefenseIncPercent(Double.parseDouble(resInfo.getAttributeValue("increasePercent")));
				wowstats.setDefensePlusDef(Double.parseDouble(resInfo.getAttributeValue("plusDefense")));
				wowstats.setDefenseRating(Double.parseDouble(resInfo.getAttributeValue("rating")));
				wowstats.setDefenseUnsureWhatValueThisIs(Double.parseDouble(resInfo.getAttributeValue("value")));
			}
		}
		return (wowstats.getDefenseRating()!=null&&wowstats.getDefenseUnsureWhatValueThisIs()!=null)
		? true : false;
	}
	
	@SuppressWarnings("unchecked")
	protected boolean loadAllExtraStats(Document source) {
		Element rootElementOfResponse = source.getRootElement();
		Element characterInformation = rootElementOfResponse.getChild("characterInfo");
		Element charaterTab = characterInformation.getChild("characterTab");
		Element extraStuffForDefense = charaterTab.getChild("defenses");		
		for(Element resInfo : (Collection<Element>) extraStuffForDefense.getChildren()){
			if(resInfo.getName().equals("resilience")){
				wowstats.setResillienceDmgPercent(Double.parseDouble(resInfo.getAttributeValue("damagePercent")));
				wowstats.setResillienceHitPercent(Double.parseDouble(resInfo.getAttributeValue("hitPercent")));
				wowstats.setResillienceRating(Double.parseDouble(resInfo.getAttributeValue("value")));
			}
			if(resInfo.getName().equals("dodge")){
				wowstats.setDodgeIncPercent(Double.parseDouble(resInfo.getAttributeValue("increasePercent")));
				wowstats.setDodgePercent(Double.parseDouble(resInfo.getAttributeValue("percent")));
				wowstats.setDodgeRating(Double.parseDouble(resInfo.getAttributeValue("rating")));
			}
			if(resInfo.getName().equals("parry")){
				wowstats.setParryIncPercent(Double.parseDouble(resInfo.getAttributeValue("increasePercent")));
				wowstats.setParryPercent(Double.parseDouble(resInfo.getAttributeValue("percent")));
				wowstats.setParryRating(Double.parseDouble(resInfo.getAttributeValue("rating")));
			}
			if(resInfo.getName().equals("block")){
				wowstats.setBlockIncPercent(Double.parseDouble(resInfo.getAttributeValue("increasePercent")));
				wowstats.setBlockPercent(Double.parseDouble(resInfo.getAttributeValue("percent")));
				wowstats.setBlockRating(Double.parseDouble(resInfo.getAttributeValue("rating")));
			}
		}
		
		//RANGED MELEE
		Element extraStuffForMeleeRanged = charaterTab.getChild("ranged");
		for(Element ranged : (Collection<Element>) extraStuffForMeleeRanged.getChildren()) {
			if(ranged.getName().equals("damage")){
				wowstats.setRnDamageDps(Double.parseDouble(ranged.getAttributeValue("dps")));
				wowstats.setRnDamageMax(Double.parseDouble(ranged.getAttributeValue("max")));
				wowstats.setRnDamageMin(Double.parseDouble(ranged.getAttributeValue("min")));
				wowstats.setRnDamagePercent(Double.parseDouble(ranged.getAttributeValue("percent")));
				wowstats.setRnDamageSpeed(Double.parseDouble(ranged.getAttributeValue("speed")));
			}
			if(ranged.getName().equals("speed")){
				wowstats.setRnSpeedHastePercent(Double.parseDouble(ranged.getAttributeValue("hastePercent")));
				wowstats.setRnSpeedHasteRating(Double.parseDouble(ranged.getAttributeValue("hasteRating")));
				wowstats.setRnHasteValue(Double.parseDouble(ranged.getAttributeValue("value")));
			}
			if(ranged.getName().equals("power")){
				wowstats.setRnPowerBase(Double.parseDouble(ranged.getAttributeValue("base")));
				wowstats.setRnPowerEffective(Double.parseDouble(ranged.getAttributeValue("effective")));
				wowstats.setRnPowerIncDps(Double.parseDouble(ranged.getAttributeValue("increasedDps")));
				wowstats.setRnPowerPetAtck(Double.parseDouble(ranged.getAttributeValue("petAttack")));
				wowstats.setRnPowerPetSpell(Double.parseDouble(ranged.getAttributeValue("petSpell")));
			}
			if(ranged.getName().equals("hitRating")){
				wowstats.setRnHitIncHitPercent(Double.parseDouble(ranged.getAttributeValue("increasedHitPercent")));
				wowstats.setRnHitPenetration(Double.parseDouble(ranged.getAttributeValue("penetration")));
				wowstats.setRnHitRating(Double.parseDouble(ranged.getAttributeValue("value")));
				wowstats.setRnHitReducedArmorPercent(Double.parseDouble(ranged.getAttributeValue("reducedArmorPercent")));
			}
			if(ranged.getName().equals("critChance")){
				wowstats.setRnCritPercent(Double.parseDouble(ranged.getAttributeValue("percent")));
				wowstats.setRnCritPlusPercent(Double.parseDouble(ranged.getAttributeValue("plusPercent")));
				wowstats.setRnCritRating(Double.parseDouble(ranged.getAttributeValue("rating")));
			}
		}
		
		wowstats.setExtraStuffHasBeenSetUp(true);
		return wowstats.isExtraStuffHasBeenSetUp();
	}
	
	private void print(Object something) {
		System.out.println(something.toString());
	}
	
	/*
	 * 
	 * GETTERS AND SETTERS
	 * 
	 */

	public String getCharName() {
		return charName;
	}

	public void setCharName(String charName) {
		this.charName = charName;
	}

	public Object getRealmName() {
		return realmName;
	}

	public void setRealmName(String realmName) {
		this.realmName = realmName;
	}

	public String getRegionType() {
		return regionType;
	}

	public void setRegionType(String regionType) {
		this.regionType = regionType;
	}

}
